# -*- coding: utf-8 -*-
import os
import datetime
import  time
import configparser

cnf_file = "myback.ini"
config = configparser.ConfigParser()
config.read(cnf_file)

stop_at =config.get("myback","stop_at")
master_container_name = config.get("master","master_container_name")
out_work_dir = config.get("myback","out_work_dir")
lastFile = os.path.join(out_work_dir,"lastFile.log")
master_container_inner_data_path = config.get("master","master_container_inner_data_path")
binlog_sql_dir = config.get("myback","binlog_sql_dir")

def restore_database_binlog(last_backup_file):
    print("################restore data from binlog###################")
    master_container_out_data_path =config.get("master","master_container_out_data_path")
    last_backup_file =os.path.join(out_work_dir,last_backup_file,"xtrabackup_info")
    backup_position_binlog_file = None
    backup_position = None
    with open(last_backup_file, 'r') as f:
        lines = f.readlines()
        for line in lines:
            if "binlog_pos = filename " in line:
                backup_position_binlog_file = line.replace("binlog_pos = filename ", "").split(",")[0]
                backup_position_binlog_file = backup_position_binlog_file.replace("'", "")
                backup_position = line.replace("binlog_pos = filename ", "").split(",")[1].strip()
                backup_position = backup_position.split(" ")[1].replace("'", "")
                pass
            else:
                continue
        binlog_path = os.path.dirname(master_container_out_data_path)
        binlog_files = os.listdir(master_container_out_data_path)
        #如果没有找到binlog，忽略binlog的还原
        if not binlog_files:
            print("未找到有效binlog")
            exit(1)

        print(binlog_files)
        #对binlog文件排序，按顺序遍历binlog，获取binlog的最后的修改时间，与stop_at做对比，判断还原的过程是否需要某个binlogfile
        binlog_files.sort()

        binlog_files_for_restore = []
        # 恢复数据库的指定时间点
        stop_at_time = datetime.datetime.strptime(stop_at, '%Y-%m-%d %H:%M:%S')
        for binlog in binlog_files:
            if (".index" in binlog or "relay" in binlog):
                continue
            if ("mysql-bin." in binlog):
                #保留最后一个备份中的binlog，以及其后面的binlog，这部分binlog会在还原的时候用到
                if (int(binlog.split(".")[-1]) >= int(backup_position_binlog_file.split(".")[-1])):
                    binlog_files_for_restore.append(binlog)

        binlog_file_count = 0
        #第一个文件，从上最后一个差异备份的position位置开始，最后一个文件，需要stop_at到指定的时间
        for binlog in binlog_files_for_restore:
            if not os.path.isdir(binlog):
                #binlog物理文件的最后修改时间
                binlog_file_updatetime = datetime.datetime.strptime(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(os.stat(binlog_path+"/"+binlog).st_mtime)),'%Y-%m-%d %H:%M:%S')
                print("{0}---{1}".format(binlog,binlog_file_updatetime))
                #判断binlog的生成时间，是否大于stop_at，对于修改时间大于stop_at的日志，需要全部还原，不需要stop_at指定截止点
                if  stop_at_time > binlog_file_updatetime :
                    if (binlog_file_count < 1):
                        if (len(binlog_files_for_restore) == 1):
                            # 找到差异备份之后的第一个binlog，需要根据差异备份的position，来过来第一个binlog文件
                            restore_commond = '''docker exec -i {0} mysqlbinlog {1}  --skip-gtids=true --start-position={2}  --stop-datetime="{3}" > {4}/{5}.sql''' \
                                .format(master_container_name,master_container_inner_data_path + binlog, backup_position, stop_at, binlog_sql_dir,binlog)
                            print("execute the following command....")
                            print(restore_commond)
                            os.system(restore_commond)
                            print("complete!!!")
                            binlog_file_count = binlog_file_count + 1
                        else:
                            # 找到差异备份之后的第一个binlog，需要根据差异备份的position，来过来第一个binlog文件
                            restore_commond = '''docker exec -i {0} mysqlbinlog {1}  --skip-gtids=true --start-position={2}  > {3}/{4}.sql''' \
                                .format(master_container_name,master_container_inner_data_path + binlog, backup_position,binlog_sql_dir,binlog)
                            print("execute the following command....")
                            print(restore_commond)
                            os.system(restore_commond)
                            print("complete!!!")
                            binlog_file_count = binlog_file_count + 1
                    else:
                        # 从第二个文件开始，binlog需要全部还原
                        restore_commond = '''docker exec -i {0} mysqlbinlog {1}  --skip-gtids=true > {2}/{3}.sql ''' \
                            .format(master_container_name,master_container_inner_data_path + binlog, binlog_sql_dir,binlog)
                        print("execute the following command....")
                        print(restore_commond)
                        os.system(restore_commond)
                        print("complete!!!")
                        binlog_file_count = binlog_file_count + 1
                else:
                      if (binlog_file_count < 1):
                          restore_commond = '''docker exec -i {0} mysqlbinlog {1}  --skip-gtids=true --start-position={2} --stop-datetime="{3}" > {4}/{5}.sql'''.format(master_container_name,master_container_inner_data_path + binlog, backup_position,stop_at, binlog_sql_dir,binlog)
                          print("execute the following command....")
                          print(restore_commond)
                          os.system(restore_commond)
                          print("complete!!!")
                          binlog_file_count = binlog_file_count + 1
                      else:
                          if (binlog_file_count >= 1):
                              restore_commond = '''docker exec -i {0} mysqlbinlog {1}  --skip-gtids=true --stop-datetime="{2}" > {3}/{4}.sql'''.format(master_container_name,master_container_inner_data_path + binlog, stop_at, binlog_sql_dir,binlog)
                              print("execute the following command....")
                              print(restore_commond)
                              os.system(restore_commond)
                              print("complete!!!")
                              binlog_file_count = binlog_file_count + 1
                              break

def get_last_file():
    last_file = None
    if os.path.exists(lastFile):
        with open(lastFile, 'r') as f:
            lines = f.readlines()
            last_line = lines[-1]  # get last backup name
            if (last_line):
                last_file = last_line
    return last_file.replace("\n","")

if __name__ == '__main__':
    restore_database_binlog(get_last_file())